package com.edu.security.config;

import com.edu.security.config.handler.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
//@EnableWebSecurity
// @EnableWebSecurity 作用: 开启SpringSecurity的自定义配置（在SpringBoot项目中可以省略此注解）
public class WebSecurityConfig {
    /**
     * public FormLoginConfigurer() { // 默认为username和 password参数名
     * super(new UsernamePasswordAuthenticationFilter(), (String)null);
     * this.usernameParameter("username");
     * this.passwordParameter("password");
     * }
     *
     * @param http
     * @return
     * @throws Exception
     */
    // 默认行为：
//    开启授权保护
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                authorize -> authorize
                        // Spring Security 按配置顺序匹配请求路径，首次匹配到的规则会立即生效，后续规则不再检查
                        .requestMatchers("/**").hasRole("ADMIN")
                        // 具有 USER_LIST 权限的用户可以访问 /list
                        .requestMatchers("/list").hasAnyAuthority("USER_LIST")
                        // 具有 USER_ADD 权限的用户可以访问 /add
                        .requestMatchers("/add").hasAnyAuthority("USER_ADD")
                        // 对所有请求开启授权保护
                        .anyRequest()
                        // 已认证的请求会被自动授权
                        .authenticated()
                // 无需授权即可访问当前页面
                // 使用表单授权方式
        ).formLogin(form -> form.loginPage("/login").permitAll()
                .usernameParameter("username") // 配置自定义的表单用户名参数，默认值是 username
                .passwordParameter("password")  // 配置自定义的表单密码参数，默认值是 password
                .failureUrl("/login?error") // 校验失败时跳转的地址 默认值是error
                .successHandler(new MyAuthenticationSuccessHandler()) // 认证成功时的处理
                .failureHandler(new MyAuthenticationFailureHandler()) // 认证失败时的处理
        ).logout(logout ->
                logout.logoutSuccessHandler(new MyLogoutHandler()) // 注销成功处理
        ).exceptionHandling(exception -> exception
                .authenticationEntryPoint(new MyAuthenticationEntryPoint()) // 请求未认证反馈
                .accessDeniedHandler(new MyAccessDeniedHandler())
        ).cors(Customizer.withDefaults() // 允许跨域访问
        ).sessionManagement(session -> session
                .maximumSessions(1)
                .expiredSessionStrategy(new MySessionInformationExpiredStrategy())
        )
        ;
//        ).formLogin(Customizer.withDefaults()); // 使用表单授权方式

//                .httpBasic(Customizer.withDefaults()); // 使用基本授权方式
        http.csrf(AbstractHttpConfigurer::disable); // 关闭csrf以允许后端模拟post请求
        return http.build();
    }

}
